///usage:  ini ROOT528
///usage:  root -l -q  readtribn1.root readtribn2.root  'validation.C(0,0)'





#ifndef __CINT__
#include "RooGlobalFunc.h"
#endif
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooGaussian.h"
#include "RooConstVar.h"
#include "RooProdPdf.h"
#include "RooAddPdf.h"
#include "RooMinuit.h"
#include "RooFitResult.h"
#include "RooPlot.h"
#include "TCanvas.h"
#include "TAxis.h"
#include "TH1.h"
#include "RooHistPdf.h"
#include "RooPlot.h"
#include "RooNLLVar.h"
#include "RooChi2Var.h"

#include "TObjString.h"
#include "TList.h"
#include "TMath.h"
#include "TLegend.h"
#include "TGraph.h"
#include "TArrayD.h"

using namespace RooFit ;

#include <iomanip>
#include <string>


///To merge histograms
//#include "templateMerger.h"


int colors [] =
{
	kRed,
	kGreen,
	kMagenta,
	kYellow,
	kRed-2,
	kGreen-2,
	kMagenta-2,
	kYellow-2,

	kRed-7,
	kGreen-7,
	kMagenta-7,
	kYellow-7,
	
	kPink,
	kBlue,
	kCyan,
	kAzure,
	
	kPink-4,
	kBlue-4,
	kCyan-4,
	kAzure-4,
	kGreen+6,
	kMagenta+6


}

///Templates && data histogram properties
TH1 * dataHist=0;
double minVal=-1e30;
double maxVal=+1e30;
double dataYield=1e0;
int bins = 0;

///Flag to understand the status of the current code execution
bool _isOk=false;



////Containers

TList * arrayOfHistos=0; /// First element is always data histogram
TList * arrayOfNames =0; 
TList * arrayOfRooDataHist=0;
TList * arrayOfRooHistPdf=0;
TList * arrayOfCanvas=0; 
//TList * arrayOfYields=0;
TList * arrayOfLegends=0;

TList * arrayOfUsedHistoNames=0;


/// Carries 'Flavor' index
 const int flavors [] = {
	2, //B
	2, //B
	2, //B
	1, //C
	1, //C
	1,  //C
	0, //Q
	0, //Q
	0  //Q
	};

/// Carries 'Cat' index
 const int positions [] = {
	0, //Bbb
	1, //bBb
	2, //bbB
	0, //Cbb
	1, //bCb
	2, //bbC
	0, //Qbb
	1, //bQb
	2  //bbQ
	};


bool selectTripleBTemplates(int _novl=0, int numFile=0)
{

std::string tSel("Trig0");

if (!arrayOfHistos) 
{arrayOfHistos = new TList();
arrayOfHistos->SetOwner(kTRUE); ///To auto-delete all content of the container
}
if (!arrayOfNames) {
arrayOfNames = new TList();
arrayOfNames->SetOwner(kTRUE); ///To auto-delete all content of the container
}

///Read histograms from file	
TFile * file0=0;
if (gROOT->GetListOfFiles()->GetSize()>numFile) file0=(TFile*) gROOT->GetListOfFiles()->At(numFile);


if (file0==0) { cout<<"Can't read data, error"<<endl;return false;}
 
///Parameters of reading 
  const int novl = 2;

  TH1F* mjjTemplate[novl];
  const std::string sovl[novl] = { "TCHPT", "TCHP6" };

///Reading histo MC (templates) for signal

_isOk=true; /// assume that all histograms are available
   
for (int iovl=0; iovl<novl; ++iovl)    
{
///mjjbtTCHPTTrig1
if (file0!=0) mjjTemplate[iovl] = (TH1F*) file0->Get(Form("mjjbt%s%s",sovl[iovl].c_str(),tSel.c_str()));
else
{
 mjjTemplate[iovl]  =0 ;

}


}


if (mjjTemplate[_novl] !=0)
	{
 		mjjTemplate[_novl]->SetDirectory(gROOT); ///To make histograms independent on file0;



///Form Name of the template:	
	
	mjjTemplate[_novl]->SetName(Form("%s_%s%s_%d","bbb",sovl[_novl].c_str(),tSel.c_str(),numFile));	
	arrayOfHistos->Add(mjjTemplate[_novl]);	
	 arrayOfNames->Add(new TObjString(Form("%s_%s%s_%d","bbb",sovl[_novl].c_str(),tSel.c_str(),numFile)));	

	
	}
else {
std::cout << "Histogram not found: " << Form("mjjbt%s%s",sovl[_novl].c_str(),tSel.c_str())<< std::endl;
_isOk=false;
}


if (!_isOk ) {std::cout<<"There are problems to read all needed signal templates from the file, error"<<std::endl;
return false;}
_isOk=false; /// reset to ini value


return true;
}

bool selectTemplates(int _novl=0, int _corr=0, int numFile=0)
{

std::string tSel("Trig0");
if (!arrayOfHistos) {
arrayOfHistos = new TList();
arrayOfHistos->SetOwner(kTRUE); ///To auto-delete all content of the container
}
if (!arrayOfNames) {
arrayOfNames = new TList();
arrayOfNames->SetOwner(kTRUE); ///To auto-delete all content of the container
}
///Read histograms from file	
TFile * file0=0;
 if (gROOT->GetListOfFiles()->GetSize()>numFile) file0=(TFile*) gROOT->GetListOfFiles()->At(numFile);


///Parameters of reading 
  const int ncateg = 3;
  const int ncorr=2;
  const int ntpat=1;
  const int nfc = 3;
  const int novl = 2;

  TH1F* mjjTemplate[nfc][novl][ncateg][ncorr][ntpat];
//  const std::string tFlav[nfc] = {"Uds", "C", "B"};
  const std::string sFlav[nfc] = {"Q", "C", "B"};

  const std::string sfc[nfc] = { "q", "c", "b" };
  const std::string sovl[novl] = { "TCHPT", "TCHP6" };

///Reading Data

if (file0==0) { cout<<"Can't read data, error"<<endl;return false;}

 TH1F* mjjdata[novl];
  for (int iovl=0; iovl<novl; ++iovl) 
  if (file0!=0)  mjjdata[iovl] = (TH1F*) file0->Get(Form("mjjbt%s%s",sovl[iovl].c_str(),tSel.c_str()));
  else mjjdata[iovl] =0;

///Putting Data into arrayOfHistos
for (int iovl=0; iovl<novl; ++iovl) 
if (mjjdata[iovl]!=0)
{
	mjjdata[iovl]->SetDirectory(gROOT); ///To make histograms independent on _file0;
	if (iovl==_novl)  {
		mjjdata[iovl]->SetName(Form("data_%s%s_%d",sovl[iovl].c_str(),tSel.c_str(),numFile));
		arrayOfHistos->Add(mjjdata[iovl]);	
		arrayOfNames->Add(new TObjString(Form("data_%s%s_%d",sovl[iovl].c_str(),tSel.c_str(),numFile)));
		_isOk=true;
	}

}

if (!_isOk) {std::cout<<"The data mass spectrum of "<<sovl[_novl]<<" operation point was not found, error"<<std::endl;
return false;
}
_isOk=false; ///reset to ini value


///Reading histo MC (templates)

_isOk=true; /// assume that all histograms are available
  for (int ifc=0; ifc<nfc; ++ifc) 
    for (int iovl=0; iovl<novl; ++iovl) 
      for (int icateg=0; icateg<ncateg; ++icateg) 
        for (int icorr=0; icorr<ncorr; ++icorr) 
          for (int itpat=0; itpat<ntpat; ++itpat) 
{

if (file0!=0) mjjTemplate[ifc][iovl][icateg][icorr][itpat] = (TH1F*) file0->Get(Form("mjjTemp_%s_%s_Cat%dCorr%dTpat%d%s",sfc[ifc].c_str(),sovl[iovl].c_str(),icateg,icorr,itpat,tSel.c_str()));
else
{
 mjjTemplate[ifc][iovl][icateg][icorr][itpat]  =0 ;

}


}

for (unsigned int i=0;i<sizeof(flavors)/sizeof(int);i++) {  
	if (mjjTemplate[flavors[i]][_novl][positions[i]][_corr][0]!=0)
	{
	 mjjTemplate[flavors[i]][_novl][positions[i]][_corr][0]->SetDirectory(gROOT); ///To make histograms independent on _file0;		

///Form Name of the template:
	TString _tmpl = "bbb";
	_tmpl.Replace(positions[i],1,sFlav[flavors[i]].c_str());

	mjjTemplate[flavors[i]][_novl][positions[i]][_corr][0]->SetName(Form("%s_%s%s_%d",_tmpl.Data(),sovl[_novl].c_str(),tSel.c_str(),numFile));	
	arrayOfHistos->Add(mjjTemplate[flavors[i]][_novl][positions[i]][_corr][0]);	
	 arrayOfNames->Add(new TObjString(Form("%s_%s%s_%d",_tmpl.Data(),sovl[_novl].c_str(),tSel.c_str(),numFile)));	

	} 

	else {
 std::cout << "Histogram not found: " << Form("mjjTemp_%s_%s_Cat%dCorr%dTpat%d%s",sfc[flavors[i]].c_str(),sovl[_novl].c_str(),positions[i],_corr,0,tSel.c_str())<<" in the file" <<file0->GetName()<< std::endl;
_isOk=false;
	}

}
if (!_isOk ) {std::cout<<"There are problems to read all needed templates from the file, error"<<std::endl;
return false;}
_isOk=false; /// reset to ini value


return true;
}

void validation(int _novl=0, int _corr=0)
{

///Read templates
for (int i=0; i<gROOT->GetListOfFiles()->GetSize();i++) {
if (!selectTemplates(_novl,_corr,i) ) {std::cout<<"Something wrong with reading bkg and data, return"<<std::endl; continue;}
if (!selectTripleBTemplates(_novl,i) ) {std::cout<<"Something wrong with reading triple bkg and data, return"<<std::endl; continue;}
}
if (arrayOfHistos && !arrayOfHistos->IsEmpty()) dataHist=(TH1*)arrayOfHistos->At(0);


if (dataHist!=0)
{
	minVal=dataHist->GetXaxis()->GetXmin();
	maxVal=dataHist->GetXaxis()->GetXmax();
	bins = dataHist->GetNbinsX();
	dataYield=dataHist->Integral();

	///Validation
	cout<<"Validation of mass data spectrum: "<<endl;
	cout<<"MinVal = "<<minVal<<endl;
	cout<<"MaxVal = "<<maxVal<<endl;
	cout<<"Number of bins = "<<bins<<endl;
	 cout<<"Number of all events (data) = "<<dataYield<<endl;

} else {cout<<"dataHist is empty, return"<<endl; return;}


RooRealVar Mjj("Mjj","Mjj",minVal,maxVal) ;
Mjj.setBins(bins);


arrayOfRooDataHist=new TList();
arrayOfRooDataHist->SetOwner(kTRUE); ///To auto-delete all content of the container

arrayOfRooHistPdf=new TList();
arrayOfRooHistPdf->SetOwner(kTRUE); ///To auto-delete all content of the container

arrayOfCanvas=new TList();
arrayOfCanvas->SetOwner(kTRUE); ///To auto-delete all content of the container

arrayOfYields = new TList();
arrayOfYields->SetOwner(kTRUE); ///To auto-delete all content of the container

arrayOfLegends=new TList();
arrayOfLegends->SetOwner(kTRUE); ///To auto-delete all content of the container


arrayOfUsedHistoNames=new TList();
arrayOfUsedHistoNames->SetOwner(kTRUE); ///To auto-delete all content of the container


for (int i=0; i<arrayOfNames->GetSize();i++)
{
TH1 * tempHis = (TH1*)arrayOfHistos->At(i);
TString _name = ( (TObjString *) arrayOfNames->At(i))->GetString();




if (tempHis!=0) 
{	

//cout<<"I'm adding "<<_name<<endl;
//cout<<"with histo "<<tempHis->GetName()<<endl;

/*
TCanvas * can =new TCanvas(); 
tempHis->Draw();
*/
arrayOfRooDataHist->Add(new  RooDataHist(_name+TString("_histdata"),_name+TString("_histdata"),Mjj,tempHis));
arrayOfRooHistPdf->Add( new RooHistPdf(_name+TString("_histpdf"),_name+TString("_histpdf"),RooArgList(Mjj),*((RooDataHist*)arrayOfRooDataHist->Last()),4)); ///Last argument is a degree of internal interpolation

/*cout<<_name<<endl;
if (_name.Contains("Bbb_")) arrayOfYields->Add( new RooRealVar(_name+TString("_yield"),_name+TString("_yield"),3331e0,0.,dataYield) );
else if (_name.Contains("bbB_")) arrayOfYields->Add( new RooRealVar(_name+TString("_yield"),_name+TString("_yield"),7608e0,0.,dataYield) );
else arrayOfYields->Add( new RooRealVar(_name+TString("_yield"),_name+TString("_yield"),dataYield/5e0,0.,dataYield) );
*/
//arrayOfYields->Add( new RooRealVar(_name+TString("_yield"),_name+TString("_yield"),dataYield/5e0,0.,dataYield) );
//arrayOfYields->Add( new RooRealVar(_name+TString("_yield"),_name+TString("_yield"),dataYield,0e0,1e20,"") );
//arrayOfYields->Add( new RooRealVar(_name+TString("_yield"),_name+TString("_yield"),0e0,0e0,dataYield*20,"") );
//arrayOfYields->Add( new RooRealVar(_name+TString("_yield"),_name+TString("_yield"),1e2,0e0,1e30,"") );

///will be added later
//arrayOfCanvas->Add (new  TCanvas(_name+TString("_canva"),_name+TString("_canva")) ); /// skip canva for data
//arrayOfLegends->Add(new TLegend(0.4,0.6,0.89,0.89));


}

}

///Validation of histPdf
cout<<"Validation: "<<endl;
//for (unsigned int i=0;i<sizeof(histonames)/sizeof(char *);i++)
///2 for! 
for (int i=0; i<arrayOfNames->GetSize();i++)
{
TGraph _combined;
TList * _combinedList = new TList();
//_combinedList->SetOwner(kTRUE); 

arrayOfLegends->Add(new TLegend(0.4,0.6,0.89,0.89));
TLegend *  leg = (TLegend*) arrayOfLegends->Last();

TString _name = ( (TObjString *) arrayOfNames->At(i))->GetString();
if (_name.Contains("data")) continue; /// skip data


if (arrayOfUsedHistoNames->FindObject(_name+TString("_histpdf_validation__Mjj"))) continue;

TH1F* histPdf=(TH1F*) ((RooHistPdf*)arrayOfRooHistPdf->At(i))->createHistogram(_name+TString("_histpdf_validation"),Mjj));




if (histPdf!=0) {


arrayOfUsedHistoNames->Add(new TObjString(histPdf->GetName()));


histPdf->SetLineColor(colors[i]);
leg->AddEntry(histPdf,_name,"l");
_combined.SetPoint(i,i,histPdf->GetMaximum());	
//cout<<"Add to combination _name "<<_name<<endl;
_combinedList->Add(histPdf);
/*
TCanvas * can =new TCanvas(); 
histPdf->Draw();
*/

}

///Find label
///Put here tokenize!!
TObjArray* tokens=_name.Tokenize(TString('_'));
TString _label = _name;
_label.ReplaceAll(TString("_")+TString(tokens->At(tokens->GetEntries()-1)->GetName()),"");

_isOk=true; ///flag to create Canvas
for (int j=i+1; j<arrayOfNames->GetSize();j++)
{
TString _name2 = ( (TObjString *) arrayOfNames->At(j))->GetString();

//cout<<"_label = "<<_label<<endl;
//cout<<"_name2 = "<< _name2<<endl;

if (arrayOfUsedHistoNames->FindObject(_name2+TString("_histpdf_validation__Mjj"))) continue;

if ( _name2.Contains("data") ||  ! _name2.Contains(_label.Data())) continue; /// skip data

TH1F* histPdf2=(TH1F*) ((RooHistPdf*)arrayOfRooHistPdf->At(j))->createHistogram(_name2+TString("_histpdf_validation"),Mjj));



if (histPdf2!=0) {

arrayOfUsedHistoNames->Add(new TObjString(histPdf2->GetName()));

//cout<<"histPdf2 = "<<histPdf2<<endl;

if (_isOk) {
arrayOfCanvas->Add (new TCanvas(TString("combined")+TString("_canva_")+Form("%d",i),TString("combined")+TString("_canva_")+Form("%d",i)));
_isOk=false;
}

histPdf2->SetLineColor(colors[j]);
leg->AddEntry(histPdf2,_name2,"l");
_combined.SetPoint(j,j,histPdf2->GetMaximum());
//cout<<"Add to combination _name2 "<<_name2<<endl;
_combinedList->Add(histPdf2);
}

} ///for j

///Plot combined

 
((TCanvas*)arrayOfCanvas->Last())->cd();
///Make Sorting
_combined.Sort(&TGraph::CompareY,kFALSE); ///descending on Y

Double_t * templPos = _combined.GetX();
_isOk=true; ///flag the histogram with the highest GetMaximum()



for (int k=0; k<_combined.GetN();k++)
{
if (templPos[k] == 0 ) continue; /// skip possible data


TString _name = ( (TObjString *) arrayOfNames->At(templPos[k]))->GetString();


	TH1F* histPdf=(TH1F*) _combinedList->FindObject(_name+TString("_histpdf_validation__Mjj"));



	if (histPdf!=0) {

//	cout<<"I've found object "<<_name<<endl;

	if (_isOk) {
		histPdf->Draw();
		_isOk=false;	

		}
	else 		histPdf->Draw("same");
		
		leg->Draw();

	
	}

}

///clean
delete _combinedList;

} /// for i

///Save figures
for (int j=0; j<arrayOfCanvas->GetEntries(); j++) {

//if (j==0) continue;

TString _posfix = Form("_Btag%d_Corr%d",_novl, _corr);
((TCanvas*)arrayOfCanvas->At(j))->SaveAs(TString(arrayOfCanvas->At(j)->GetName())+_posfix+TString(".eps"));

}



delete arrayOfHistos;
delete arrayOfRooDataHist;
delete arrayOfRooHistPdf;
//delete arrayOfCanvas;
//delete arrayOfLegends;

delete arrayOfUsedHistoNames;



return;


}